package com.seckill.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.seckill.goods.feign.SkuFeign;
import com.seckill.goods.pojo.Sku;
import com.seckill.search.pojo.Page;
import com.seckill.search.pojo.SkuInfo;
import com.seckill.search.service.SkuInfoService;
import com.seckill.util.Result;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.cert.ocsp.Req;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/*****
 * @Author: http://www.itheima.com
 * @Project: seckillproject
 * @Description: com.seckill.search.service.impl.SkuInfoServiceImpl
 ****/
@Slf4j
@Service
public class SkuInfoServiceImpl implements SkuInfoService {

    @Autowired
    private SkuFeign skuFeign;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    public static final String indexName = "goodsindex";

    /***
     * 秒杀搜索列表
     * @param searchMap
     * @return
     */
    @Override
    public Page<SkuInfo> search(Map<String, String> searchMap) throws IOException {
        //时间  starttime
        String starttime = searchMap.get("starttime");
        if (!ObjectUtils.isEmpty(starttime)) {
            starttime = parseTime(starttime);
        }

        //根据bgtime实现分页搜索
        Page<SkuInfo> page = new Page<SkuInfo>();
        SearchRequest request = new SearchRequest(indexName);
        request.source().query(QueryBuilders.termQuery("bgtime", starttime));
        request.source().from(0).size(100);
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);

        List<SkuInfo> content = new ArrayList<SkuInfo>();
        for (SearchHit hit : response.getHits()) {
            SkuInfo skuInfo = JSON.parseObject(hit.getSourceAsString(), SkuInfo.class);
            content.add(skuInfo);
        }
        //集合处理
        if (content != null) {
            List<String> ids = new ArrayList<String>();
            for (SkuInfo skuInfo : content) {
                ids.add(skuInfo.getId());
            }
            //执行查询
            List<Sku> skuList = skuFeign.seckillPrice(ids);
            for (SkuInfo skuInfo : content) {
                for (Sku sku : skuList) {
                    if (sku.getId().equals(skuInfo.getId())) {
                        skuInfo.setSeckillPrice(sku.getSeckillPrice().longValue());
                        skuInfo.setPrice(sku.getPrice().longValue());
                        break;
                    }
                }
            }
        }
        page.setContent(content);
        return page;
    }

    /***
     * 获取当前页->pageNum
     */
    public Integer pageConveter(Map<String, String> searchMap) {
        try {
            return Integer.parseInt(searchMap.get("pageNum"));
        } catch (NumberFormatException e) {
            return 1;
        }
    }

    /***
     * 增量操作  ->删除索引   type=3
     *           ->修改索引   type=2
     *           ->添加索引   type=1
     */
    @Override
    public void modify(Integer type, SkuInfo skuInfo) {
        try {
            if (type == 1 || type == 2) {
                System.out.println("Search:" + skuInfo.getId() + "," + skuInfo.getBgtime());
                //增加-修改
                //skuInfoMapper.save(skuInfo);
                IndexRequest request = new IndexRequest(indexName);
                request.source(JSON.toJSONString(skuInfo), XContentType.JSON).id(skuInfo.getId());
                restHighLevelClient.index(request, RequestOptions.DEFAULT);
            } else {
                //skuInfoMapper.deleteById(skuInfo.getId());
                DeleteRequest deleteRequest = new DeleteRequest(indexName);
                deleteRequest.id(skuInfo.getId());
                restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /***
     * 添加索引
     * @param sku
     */
    @Override
    public void addIndex(Sku sku) throws IOException {
        SkuInfo skuInfo = JSON.parseObject(JSON.toJSONString(sku), SkuInfo.class);
        if (skuInfo.getSeckillBegin() != null) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHH");
            skuInfo.setBgtime(simpleDateFormat.format(skuInfo.getSeckillBegin()));
        }
        IndexRequest request = new IndexRequest(indexName);
        request.source(JSON.toJSONString(skuInfo), XContentType.JSON).id(skuInfo.getId());
        restHighLevelClient.index(request, RequestOptions.DEFAULT);
    }

    @Override
    public void batchAddIndex(List<Sku> skus) throws IOException {
        //3.循环总页数，查询每页的数据
        BulkRequest request = new BulkRequest().setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
        //4.将数据转换成SkuInfo
        List<SkuInfo> skuInfos = JSON.parseArray(JSON.toJSONString(skus), SkuInfo.class);

        //将开始时间转换成字符串类型
        for (SkuInfo skuInfo : skuInfos) {
            if (skuInfo.getSeckillBegin() != null) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHH");
                skuInfo.setBgtime(simpleDateFormat.format(skuInfo.getSeckillBegin()));
            }
            //创建IndexRequest
            IndexRequest indexRequest = new IndexRequest(indexName);
            indexRequest.
                    source(JSON.toJSONString(skuInfo), XContentType.JSON).
                    id(skuInfo.getId());
            request.add(indexRequest);
        }
        //批量保存
        restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
    }

    @Override
    public void clear() throws IOException {
        //删除索引
        deleteAll();
        //重建索引
        createIndex(indexName);
    }

    @Override
    public void deleteById(String id) throws IOException {
        restHighLevelClient.delete(new DeleteRequest(indexName,id), RequestOptions.DEFAULT);
    }


    /***
     * 批量导入
     */
    @Override
    public void addAll() throws IOException {
        //删除索引
        deleteAll();
        //重建索引
        createIndex(indexName);

        //分页数据
        int page = 1, size = 5000;

        //1.查询总记录数
        Result totalResult = skuFeign.count();
        Integer total = Integer.valueOf(totalResult.getData().toString());
        //2.根据总记录数计算总页数
        int totalpages = total % size == 0 ? total / size : (total / size) + 1;
        //3.循环总页数，查询每页的数据
        BulkRequest request = new BulkRequest().setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
        for (int i = 0; i < totalpages; i++) {
            List<Sku> skus = skuFeign.list(page, size);
            if (CollectionUtils.isEmpty(skus)) {
                return;
            }
            page++;
            //4.将数据转换成SkuInfo
            List<SkuInfo> skuInfos = JSON.parseArray(JSON.toJSONString(skus), SkuInfo.class);
            log.info("导入{}条数据", skuInfos.size());
            //将开始时间转换成字符串类型
            for (SkuInfo skuInfo : skuInfos) {
                if (skuInfo.getSeckillBegin() != null) {
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHH");
                    skuInfo.setBgtime(simpleDateFormat.format(skuInfo.getSeckillBegin()));
                }
                //创建IndexRequest
                IndexRequest indexRequest = new IndexRequest(indexName);
                indexRequest.
                        source(JSON.toJSONString(skuInfo), XContentType.JSON).
                        id(skuInfo.getId());
                request.add(indexRequest);
            }
            //批量保存
            restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
            log.info("导入第{}页数据完成", page-1);
        }
        log.info("导入数据完成");
    }

    @Override
    public void deleteAll() {
        //skuInfoMapper.deleteAll();
        try {
            // 1.创建Request对象
            GetIndexRequest request = new GetIndexRequest(indexName);
            // 2.发送请求
            boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
            if (exists) {
                deleteIndex(indexName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加数据到索引库
     *
     * @param skuInfo
     */
    @Override
    public void importIndex(SkuInfo skuInfo) throws IOException {
        if (skuInfo.getSeckillBegin() != null) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHH");
            skuInfo.setBgtime(simpleDateFormat.format(skuInfo.getSeckillBegin()));
        }
        IndexRequest request = new IndexRequest(indexName);
        request.source(JSON.toJSONString(skuInfo), XContentType.JSON).id(skuInfo.getId());
        restHighLevelClient.index(request, RequestOptions.DEFAULT);
    }

    //时间转换
    public String parseTime(String time) {
        try {
            //202007301600
            if (time.length() > 12) {
                time = time.substring(0, 12);
            }
            while (time.length() < 12) {
                time += "0";
            }
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmm");
            SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyyMMddHH");
            Date date = simpleDateFormat.parse(time);
            return simpleDateFormat1.format(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }


    /***
     * 删除索引库
     */
    public void deleteIndex(String indexName) throws IOException {
        // 1.创建Request对象
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        // 2.发送请求
        restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
    }

    /**
     * 创建索引库
     *
     * @param indexName
     * @throws IOException
     */
    @Override
    public void createIndex(String indexName) throws IOException {
        // 1.准备Request      PUT /hotel
        CreateIndexRequest request = new CreateIndexRequest(indexName);
        // 2.准备请求参数
        request.source(MAPPING_TEMPLATE, XContentType.JSON);
        // 3.发送请求
        restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
    }


    public static final String MAPPING_TEMPLATE = "{\"mappings\": {\"properties\": {\"id\": {\"type\":\"keyword\"},\"name\":{\"type\":\"text\",\"analyzer\":\"ik_max_word\"},\"price\":{\"type\":\"long\"},\"seckillPrice\":{\"type\":\"long\"},\"image\":{\"type\": \"keyword\"},\"updateTime\":{\"type\": \"date\"},\"category1Id\":{\"type\": \"keyword\"},\"category2Id\":{\"type\":\"keyword\"},\"category3Id\":{\"type\": \"keyword\"},\"category1Name\":{\"type\":\"keyword\"},\"category2Name\":{\"type\": \"keyword\"},\"category3Name\":{\"type\":\"keyword\"},\"brandName\":{\"type\":\"keyword\"},\"bgtime\":{\"type\":\"keyword\"},\"brandId\":{\"type\":\"keyword\"},\"seckillBegin\":{\"type\":\"date\"},\"seckillEnd\":{\"type\":\"date\"},\"status\":{\"type\":\"integer\"},\"spec\":{\"type\": \"keyword\"},\"points\":{\"type\":\"integer\"}}}}";

}
